﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel.Channels;
using System.Text;
using System.Threading.Tasks;

namespace ebMS3dotnet.Core
{
    class ebMS3PackagingReplyChannel:ebMS3PackagingChannelBase<IReplyChannel>, IReplyChannel        
    {
        internal ebMS3PackagingReplyChannel(ChannelManagerBase channelManager,
            IReplyChannel innerChannel)
            : base(channelManager, innerChannel) { }

        public IAsyncResult BeginReceiveRequest(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return InnerChannel.BeginReceiveRequest(timeout, callback, state);
        }

        public IAsyncResult BeginReceiveRequest(AsyncCallback callback, object state)
        {
            return InnerChannel.BeginReceiveRequest(callback, state);
        }

        public IAsyncResult BeginTryReceiveRequest(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return InnerChannel.BeginTryReceiveRequest(timeout, callback, state);
        }

        public IAsyncResult BeginWaitForRequest(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return InnerChannel.BeginWaitForRequest(timeout, callback, state);
        }

        public RequestContext EndReceiveRequest(IAsyncResult result)
        {
            var requestContext = InnerChannel.EndReceiveRequest(result);
            if(requestContext != null)
             ProcessRequest(requestContext);
            return requestContext;
        }

        public bool EndTryReceiveRequest(IAsyncResult result, out RequestContext context)
        {
            var success = InnerChannel.EndTryReceiveRequest(result, out context);
            if(context != null)
                ProcessRequest(context);
            return success;
        }

        public bool EndWaitForRequest(IAsyncResult result)
        {
            return InnerChannel.EndWaitForRequest(result);
        }

        public System.ServiceModel.EndpointAddress LocalAddress
        {
            get { return InnerChannel.LocalAddress; }
        }

        public RequestContext ReceiveRequest(TimeSpan timeout)
        {
            var requestContext = InnerChannel.ReceiveRequest(timeout);
            if(requestContext != null)
                ProcessRequest(requestContext);
            return requestContext;
        }

        public RequestContext ReceiveRequest()
        {
            return InnerChannel.ReceiveRequest();
        }

        public bool TryReceiveRequest(TimeSpan timeout, out RequestContext context)
        {
            return InnerChannel.TryReceiveRequest(timeout, out context);
        }

        public bool WaitForRequest(TimeSpan timeout)
        {
            return InnerChannel.WaitForRequest(timeout);
        }

        private void ProcessRequest(RequestContext context)
        {
                var properties = GetProperty<ChannelParameterCollection>();
                var headers = context.RequestMessage.Headers;
                int headerIndex = headers.FindHeader(Constants.EBMS3_HEADERNAME, Constants.EBMS3_NAMESPACE);
                if (headerIndex == -1)
                    throw new InvalidOperationException("ebMS3 header was not found on the incoming message.");

                context.RequestMessage.Headers.UnderstoodHeaders.Add(headers[headerIndex]);      
        }
    }
}
